package com.lsl.rdf.utils.encrypt;

import com.lsl.rdf.encrypt.EncryptOrDecryptException;
import org.apache.commons.lang.StringUtils;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;

/**
 * Created by lsl on 2021/6/1.
 */
public class Md5Util {

    /**
     * 将字符串使用md5加密为字节数组
     *
     * @param source 源字符串
     * @return md5 加密字节
     */
    private static byte[] encode2byte(String source, boolean thrEx) {
        byte[] result = null;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.reset();
            md.update(source.getBytes(StandardCharsets.UTF_8));
            result = md.digest();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            if (thrEx) {
                throw new EncryptOrDecryptException("Md5Util.encode2byte 加密失败", e);
            }
        }
        return result;
    }

    /**
     * 将源字符串使用md5加密为32位的16进制数
     *
     * @param source 要加密字符串
     * @param thrEx  是否抛出异常，发生异常时
     * @return 加密后字符串 (小写)
     */
    public static String md5(String source, boolean thrEx) {
        if (StringUtils.isBlank(source)) {
            return null;
        }
        byte[] bytes = encode2byte(source, thrEx);

        StringBuilder hexString = new StringBuilder();
        for (byte data : bytes) {
            String hex = Integer.toHexString(0xff & data);
            if (hex.length() == 1) {
                hexString.append("0");
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

    /**
     * 将源字符串使用md5加密为32位的16进制数
     *
     * @param source 要加密字符串
     * @return 加密后字符串 (小写)
     */
    public static String md5(String source) {
        if (StringUtils.isBlank(source)) {
            return null;
        }
        return md5(source, false);
    }

    /**
     * 将源字符串使用md5加密为32位的16进制数
     *
     * @param source 要加密字符串
     * @return 加密后字符串 (大写)
     */
    public static String MD5(String source) {
        if (StringUtils.isBlank(source)) {
            return null;
        }
        String md5 = md5(source);
        return Objects.nonNull(md5) ? md5.toUpperCase() : null;
    }

    /**
     * 验证字符串是否匹配
     *
     * @param unknown 原字符串
     * @param okHex   加密后字符串
     * @return true or false
     */
    public static boolean validate(String unknown, String okHex) {
        if (StringUtils.isBlank(unknown) || StringUtils.isBlank(okHex)) {
            return false;
        }
        return okHex.toLowerCase().equals(md5(unknown));
    }

    private Md5Util() {
    }
}
